
import axios from "axios";
import qs from "qs";
/* 
  @param{object} config {
    url:'',
    method:'',默认 'get'
    headers:{},
    params:{},
    data:{},
  }
*/
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
export const request = (config) => {

  const instance = axios.create({
    baseURL: 'https://api.virapi.com',
    timeout: 3000,
    headers: {
      // 'Content-Type': 'application/x-www-form-urlencoded',
      "app-token": '$2a$10$29LBQK.7YTrIxCWNIWzbWeGv/d4qEIK6qNxtmtpWLxrFFI5Iub9bq'
    }
  })
  console.log(instance.defaults.headers.post['Content-Type'])
  // instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
  //2.axios的拦截器
  //2.1请求拦截的作用
  instance.interceptors.request.use(config => {
    // console.log(config);
    //1.比如说config中的一些信息不符合服务器的要求，需要加工一下
    //2.比如每次发送网络请求时，都希望在界面中显示一个请求的图标
    //3.某些网络请求（比如登录（token））必须携带一些特殊的信息
    //4.取消请求主要有两个场景：
    // 当请求方式method，请求路径url，请求参数（get为params，post为data）都相同时，可以视为同一个请求发送了多次，需要取消之前的请求
    // 当路由切换时，需要取消上个路由中未完成的请求

    removePending(config) // 在请求开始前，对之前的请求做检查取消操作
    addPending(config) // 将当前请求添加到 pending 中
    return config
  }, err => {

    // 处理请求错误
    return Promise.reject(err)
  })
  //2.2响应拦截
  instance.interceptors.response.use(res => {
    // console.log(res);
    removePending(res)
    // 接口返回 retcode 不为 0 时需要报错，请求设置了 noError 为 true 则这个接口不报错
    //  if (
    //   // response.data.retcode &&
    //   !response.config.noError
    // ) {
    //   if (response.data.message) {
    //     // Vue.prototype.$cus_message({
    //     //   showClose: true,
    //     //   message: response.data.message,
    //     //   type: 'error',
    //     // });
    //   }
    //   return Promise.reject(res.data);
    // }
    return res.data
  }, err => {
    // 异常情况console，方便排查问题
    console.log('error', err)
    // 移除重复请求
    removePending(err.config || {})

    return Promise.reject(err)
  })

  return instance(config)
}

// 声明一个 Map 用于存储每个请求的标识 和 取消函数
const pending = new Map()
/**
 * 添加请求
 * @param {Object} config 
 */
const addPending = (config) => {
  const url = [
    config.method,
    config.url,
    qs.stringify(config.params),
    qs.stringify(config.data)
  ].join('&')
  // config中有 noCancel标识表示不需要加入pending
  if(!config.noCancel){
    let controller = new AbortController();
    const signal = controller.signal;
    config.signal = signal
    if (!pending.has(url)) { // 如果 pending 中不存在当前请求，则添加进去
      pending.set(url, controller)
    }
    // config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
    //   // cancel 函数的参数会作为 promise 的 error 被捕获
    //   if (!pending.has(url)) { // 如果 pending 中不存在当前请求，则添加进去
    //     pending.set(url, cancel)
    //   }
    // })
  }
}
/**
 * 移除请求
 * @param {Object} config 
 */
const removePending = (config) => {
  const url = [
    config.method,
    config.url,
    qs.stringify(config.params),
    qs.stringify(config.data)
  ].join('&')
  if (pending.has(url)) { // 如果在 pending 中存在当前请求标识，需要取消当前请求，并且移除
    // const cancel = pending.get(url)
    // cancel(url)
    const controller = pending.get(url)
    // 取消请求
    controller.abort()
    pending.delete(url)
  }
}
/**
 * 清空 pending 中的请求（在路由跳转时调用）
 */
// const clearPending = () => {
//   for (const [url, controller] of pending) {
//     controller.abort()
//   }
// //   for (const [url, cancel] of pending) {
// //     cancel(url)
// //   }
//   pending.clear()
// }